#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h> 
#include <stdio.h>

// ==== Definicion de constantes y variables globales =============
const double radioPinza = 0.05;
const double distanciaInicialPinza = 0.2;

static int hombro1 = 45;
static int hombro2 = 40;
static int codo = -20;
static double distanciaCentro;
GLfloat matVerde[] = {0.0, 1.0, 0.0, 1.0};
GLfloat matAzul[] = {0.0, 0.0, 1.0, 1.0};
GLfloat matRojo[] = {1.0, 0.0, 0.0, 0.0};
GLfloat matBlanco[] = {1.0, 1.0, 1.0, 1.0};

// ==== Funci�n de callback del teclado ===========================
void teclado(unsigned char key, int x, int y) {
  switch (key) { 
  case '1': hombro1 = (hombro1++) % 360; break;
  case '2': hombro1 = (hombro1--) % 360; break;
  case 'q': hombro2 = (hombro2++) % 360; break;
  case 'w': hombro2 = (hombro2--) % 360; break;
  case 'a': codo = (codo++) % 360; break;
  case 's': codo = (codo--) % 360; break;
  case 'z': if (distanciaCentro > radioPinza) distanciaCentro -= 0.01; break;
  case 'x': if (distanciaCentro < distanciaInicialPinza) distanciaCentro += 0.01; break;
  }
  glutPostRedisplay();
}

// ==== Funci�n de dibujado =======================================
void dibujar() { 
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 
    gluLookAt(0.0, 1.0, 6.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0);

    glRotatef(100, 1.0, 0.0, 0.0);

    glPushMatrix();
    glMaterialfv(GL_FRONT, GL_DIFFUSE, matRojo);
    glutSolidTorus(0.1,1,8,8);
    glPopMatrix();

    glRotatef(hombro1, 0.0, 0.0, 1.0);
    glRotatef(hombro2, 0.0, 1.0, 0.0);
    glTranslatef(1.0, 0.0, 0.0);
    glPushMatrix();
    glScalef (2.0, 0.7, 0.1);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, matVerde);
    glutSolidCube(1.0);
    glPopMatrix();

    glTranslatef(1.0,0.0,0.0);  // Avanzamos al extremo
    glRotatef(codo, 0.0, 1.0, 0.0);
    glTranslatef(1.0,0.0,0.0);  // Hasta la mitad
    glPushMatrix();
    glScalef (2.0, 0.7, 0.1);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, matAzul);
    glutSolidCube(1.0);
    glPopMatrix();

    glTranslatef(1.0,0.0,0.0);  // Avanzamos al extremo
    glRotatef(90, 0.0, 1.0, 0.0);
    glTranslatef(0.0,distanciaCentro,0.0);
    glPushMatrix();
    glMaterialfv(GL_FRONT, GL_DIFFUSE, matBlanco);
    glutSolidCone(radioPinza, 0.2, 15, 12);
    glPopMatrix();

    glTranslatef(0.0,(distanciaCentro*-2),0.0);
    glPushMatrix();
    glMaterialfv(GL_FRONT, GL_DIFFUSE, matBlanco);
    glutSolidCone(radioPinza, 0.2, 15, 12);
    glPopMatrix();

    glutSwapBuffers();      
} 

void escalar(int w, int h) 
{ 
  // Viewport para dibujar en toda la ventana 
  glViewport( 0, 0, w, h ); 
  
  // Actualizamos en la matriz de proyecci�n el ratio ancho/alto 
  glMatrixMode( GL_PROJECTION ); 
  glLoadIdentity(); 
  gluPerspective( 60., (double)w/(double)h, 1., 20. ); 
  
  // Volvemos al modo Vista de Modelo 
  glMatrixMode( GL_MODELVIEW ); 
}

int main( int argc, char** argv ) 
{ 
  GLfloat posluz[] = {0.0, 4.0, 8.0, 0.0}; 
  GLfloat luz[] = {1.0, 1.0, 1.0, 1.0};

  distanciaCentro = distanciaInicialPinza;

  glutInit( &argc, argv ); 
  
  glutInitDisplayMode( GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE ); 
  glutInitWindowSize(640, 480); 
  glutCreateWindow( "Practicas IG - Sesion 3" ); 
  
  glClearColor(0.2, 0.2, 0.2, 1.0);
  glShadeModel(GL_FLAT);
  glLightfv(GL_LIGHT0, GL_POSITION, posluz);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, luz);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_DEPTH_TEST);

  // Registro de funciones de callback
  glutDisplayFunc(dibujar); 
  glutReshapeFunc(escalar); 
  glutKeyboardFunc(teclado);
  
  glutMainLoop();  
  return 0; 
} 
